import gtk

from gtksimple import *
import tree
import listmodel

class Box(gtk.Box):
    pass
    
class VBox(gtk.VBox):
    def pack_start(self, widget, **kwargs):
        new_kwargs = kwargs.copy()
        new_kwargs.setdefault('expand', False)
        for key in ['xoptions', 'yoptions']:
            if key in new_kwargs:
                del new_kwargs[key]
        super(VBox, self).pack_start(widget, **new_kwargs)
    def pack_end(self, widget, **kwargs):
        new_kwargs = kwargs.copy()
        new_kwargs.setdefault('expand', False)
        for key in ['xoptions', 'yoptions']:
            if key in new_kwargs:
                del new_kwargs[key]
        super(VBox, self).pack_end(widget, **new_kwargs)
        
        
class HBox(gtk.HBox):
    def pack_start(self, widget, **kwargs):
        new_kwargs = kwargs.copy()
        new_kwargs.setdefault('expand', False)
        for key in ['xoptions', 'yoptions']:
            if key in new_kwargs:
                del new_kwargs[key]
        super(HBox, self).pack_start(widget, **new_kwargs)
    def pack_end(self, widget, **kwargs):
        new_kwargs = kwargs.copy()
        new_kwargs.setdefault('expand', False)
        for key in ['xoptions', 'yoptions']:
            if key in new_kwargs:
                del new_kwargs[key]
        super(HBox, self).pack_end(widget, **new_kwargs)

class Table(gtk.Table):
    def __init__(self, **kwargs):
        kwargs.setdefault('columns', 2)
        super(Table, self).__init__(**kwargs)
        self._child_widgets = {}
    def attach(self, *args, **kwargs):
        expand = kwargs.get('expand')
        if expand is not None:
            if expand:
                kwargs.setdefault('xoptions', gtk.EXPAND | gtk.FILL)
                kwargs.setdefault('yoptions', gtk.EXPAND | gtk.FILL)
            del kwargs['expand']
        else:
            kwargs.setdefault('xoptions', gtk.FILL)
            kwargs.setdefault('yoptions', gtk.FILL)
        super(Table, self).attach(*args, **kwargs)
        
    def pack_start(self, *args, **kwargs):
        self.pack_end(*args, **kwargs)
    def pack_end(self, *args, **kwargs):
        if len(args) < 5:
            widget = args[0]
            sizeX = self.get_property('n-columns')
            sizeY = self.get_property('n-rows')
            loc = None
            for y in range(sizeY):
                for x in range(sizeX):
                    if (x, y) not in self._child_widgets:
                        loc = (x, y)
                        break
                if loc is not None:
                    break
            if loc is None:
                self.resize(sizeY+1, sizeX)
                loc = (0, sizeY+1)
            #self.attach(widget, loc[1], loc[1]+1, loc[0], loc[0]+1, **kwargs) 
            self.attach(widget, loc[0], loc[0]+1, loc[1], loc[1]+1, **kwargs)
            self._child_widgets.update({loc:widget})
            
class Label(gtk.Label):
    pass
    
class Frame(gtk.Frame):
    def __init__(self, **kwargs):
        wid_kwargs = {'label':kwargs.get('label', '')}
        super(Frame, self).__init__(**wid_kwargs)
        self.topwidget = kwargs.get('topwidget', VBox)()
        self.add(self.topwidget)
    def pack_start(self, *args, **kwargs):
        self.topwidget.pack_start(*args, **kwargs)
    def attach(self, *args, **kwargs):
        self.topwidget.pack_start(*args, **kwargs)
class Expander(gtk.Expander):
    def __init__(self, **kwargs):
        expanded = kwargs.get('expanded', True)
        wid_kwargs = {'label':kwargs.get('label', '')}
        super(Expander, self).__init__(**wid_kwargs)
        self.topwidget = kwargs.get('topwidget', VBox())
        self.add(self.topwidget)
        self.set_expanded(expanded)
    def pack_start(self, *args, **kwargs):
        self.topwidget.pack_start(*args, **kwargs)
    def attach(self, *args, **kwargs):
        self.topwidget.attach(*args, **kwargs)
class ScrolledWindow(gtk.ScrolledWindow):
    def __init__(self, *args, **kwargs):
        super(ScrolledWindow, self).__init__(*args, **kwargs)
        self.viewport = gtk.Viewport()
        self.add(self.viewport)
    def add(self, *args, **kwargs):
        if isinstance(args[0], gtk.Viewport):
            super(ScrolledWindow, self).add(*args, **kwargs)
        else:
            self.viewport.add(*args, **kwargs)
    def pack_start(self, *args, **kwargs):
        self.viewport.add(*args, **kwargs)
    def remove(self, *args, **kwargs):
        self.viewport.remove(*args, **kwargs)

class Pane(object):
    def pack_start(self, widget, **kwargs):
        if self.get_child1() is None:
            self.add1(widget)
        elif self.get_child2() is None:
            self.add2(widget)
class HPane(gtk.HPaned, Pane):
    pass
class VPane(gtk.VPaned, Pane):
    pass

class Notebook(gtk.Notebook):
    def add_page(self, **kwargs):
        widget = kwargs.get('widget')
        label = gtk.Label(kwargs.get('label', ''))
        self.append_page(widget, label)
        
class MenuBar(gtk.MenuBar):
    def __init__(self, **kwargs):
        super(MenuBar, self).__init__()
        self.menu_order = kwargs.get('menu_order')
        self.menu_info = kwargs.get('menu_info')
        for key in self.menu_info.iterkeys():
            val = self.menu_info[key]
            if type(val) == list or type(val) == tuple:
                d = {}
                for s in val:
                    d.update({s:{'name':s}})
                self.menu_info[key] = d
        self.menus = {}
        for key in self.menu_order:
            val = self.menu_info[key]
            self.add_menu(key, **val)
        self.show()
    def add_menu(self, id, **kwargs):
        menu = Menu(menubar=self, name=id, item_info=kwargs)
        self.menus.update({id:menu})
        self.append(menu.menuitem)
        
class Menu(gtk.Menu):
    def __init__(self, **kwargs):
        super(Menu, self).__init__()
        self.menuitem = MenuItem(name=kwargs.get('name'))
        self.menuitem.set_submenu(self)
        self.menubar = kwargs.get('menubar')
        self.item_info = kwargs.get('item_info')
        self.items = {}
        for key, val in self.item_info.iteritems():
            self.add_item(key, **val)
    def add_item(self, id, **kwargs):
        item = MenuItem(**kwargs)
        self.items.update({id:item})
        self.append(item)

class MenuItem(gtk.MenuItem):
    def __init__(self, **kwargs):
        self.item_name = kwargs.get('name')
        super(MenuItem, self).__init__(label=self.item_name)
        self.show()
    
btn_info = {'cancel':(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL), 
            'open':(gtk.STOCK_OPEN, gtk.RESPONSE_OK), 
            'save':(gtk.STOCK_SAVE, gtk.RESPONSE_OK)}
class FileDialog(BaseObject):
    modes = {'open':gtk.FILE_CHOOSER_ACTION_OPEN, 
             'save':gtk.FILE_CHOOSER_ACTION_SAVE, 
             'select_folder':gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, 
             'create_folder':gtk.FILE_CHOOSER_ACTION_CREATE_FOLDER}
    default_buttons = {'open':(btn_info['cancel'] + btn_info['open']), 
                       'save':(btn_info['cancel'] + btn_info['save'])}
    filter_types = ['pattern', 'mime']
    def __init__(self, **kwargs):
        super(FileDialog, self).__init__(**kwargs)
        self.register_signal('response')
        self.mode = kwargs.get('mode')
        self.overwrite_confirmation = kwargs.get('overwrite_confirmation', True)
        self.current_folder = kwargs.get('current_folder')
        filters = kwargs.get('filters', {})
        ##{FilterName:[[filter_type, filter_data],...]}
        self.filters = {}
        for key, val in filters.iteritems():
            self.add_filter(key, val)
        dlg_kwargs = {}
        if 'label' in kwargs:
            dlg_kwargs.update({'title':kwargs.get('label')})
        dlg_kwargs.update({'buttons':kwargs.get('buttons', self.default_buttons[self.mode])})
        dlg_kwargs.update({'action':self.modes[self.mode]})
        self.dialog = gtk.FileChooserDialog(**dlg_kwargs)
        for filter in self.filters.itervalues():
            self.dialog.add_filter(filter)
        if self.current_folder is not None:
            self.dialog.set_current_folder_uri(self.current_folder)
        self.dialog.set_do_overwrite_confirmation(self.overwrite_confirmation)
        #self.dialog.connect('response', self.on_dialog_response)
        
    def show(self):
        response = self.dialog.run()
        resp_dict = {'dialog':self, 'response':False}
        if response == gtk.RESPONSE_OK:
            resp_dict.update({'response':True, 'filename':self.dialog.get_filename()})
        self.emit('response', **resp_dict)
        self.dialog.destroy()
        return resp_dict
    
    def add_filter(self, name, filter_data):
        f = gtk.FileFilter()
        f.set_name(name)
        for filter in filter_data:
            if filter[0] == 'pattern':
                f.add_pattern(filter[1])
            elif filter[0] == 'mime':
                f.add_mime_type(filter[1])
        self.filters.update({name:f})
        
    def on_dialog_response(self, *args):
        print args
        
    
class ColorSelection(Color):
    def __init__(self, **kwargs):
        super(ColorSelection, self).__init__(**kwargs)
        self.topwidget = Frame(**kwargs)
        self.topwidget.pack_start(self.widget)
    def setup_widgets(self):
        self.widget = gtk.ColorSelection()
        hbox = self.widget.get_children()[0]
        vbox = hbox.get_children()[1]
        hbox.remove(vbox)
        exp = Expander(label='Values', expanded=False)
        exp.pack_start(vbox)
        hbox.pack_start(exp) 
        exp.show_all()
        self.widget.connect('color-changed', self.on_widget_update)
    def get_widget_color(self):
        return self.widget.get_current_color()
    def set_widget_color(self, gcolor):
        self.widget.set_current_color(gcolor)
    
class ColorBtn(Color):
    def __init__(self, **kwargs):
        super(ColorBtn, self).__init__(**kwargs)
        self.topwidget = self.widget
    def setup_widgets(self):
        self.widget = gtk.ColorButton()
        self.widget.connect('color-set', self.on_widget_update)
    def get_widget_color(self):
        return self.widget.get_color()
    def set_widget_color(self, gcolor):
        self.widget.set_color(gcolor)

class Entry(EntryBuffer):
    def setup_widgets(self, **kwargs):
        self.topwidget = Frame(label=kwargs.get('label', ''))
        self.widget = gtk.Entry()
        self.widget.connect('activate', self.on_widget_activate)
        self.topwidget.pack_start(self.widget)
    def get_widget_text(self):
        return self.widget.get_text()
    def set_widget_text(self, text):
        self.widget.set_text(text)
    def on_widget_activate(self, *args):
        self.set_object_text(self.get_widget_text())
        
class Text(TextBuffer):
    def __init__(self, **kwargs):
        self.name = kwargs.get('name', '')
        self.topwidget = Frame(label=self.name)
        kwargs.setdefault('widget', gtk.TextView())
        super(Text, self).__init__(**kwargs)
        expand = kwargs.get('expand', True)
        self.topwidget.pack_start(self.widget, expand=expand)

class Tree(tree.TreeViewConnector):
    def __init__(self, **kwargs):
        super(Tree, self).__init__(**kwargs)
        self.name = kwargs.get('name', '')
        self.topwidget = Frame(label=self.name, topwidget=ScrolledWindow)
        #self.scrolled_win = ScrolledWindow()
        #self.scrolled_win.add(self.widget)
        self.topwidget.topwidget.add(self.widget)

class SpinBtn(Spin):
    def __init__(self, **kwargs):
        super(SpinBtn, self).__init__(**kwargs)
        if kwargs.get('no_frame', False):
            self.topwidget = Frame(label=kwargs.get('label', ''))
            self.topwidget.pack_start(self.widget)
        else:
            self.topwidget = self.widget

class RadioBtn(Radio):
    def __init__(self, **kwargs):
        super(RadioBtn, self).__init__(**kwargs)
        self.topwidget = Frame(label=self.attribute.name)
        for key, val in self.attribute.parameters.iteritems():
            self.topwidget.pack_start(self.widgets[val])
            
class TreeList(listmodel.ListModelTree):
    def __init__(self, **kwargs):
        self.name = kwargs.get('name', '')
        self.topwidget = Frame(label=self.name)
        super(TreeList, self).__init__(**kwargs)
        self.topwidget.pack_start(self.widget)

class Combo(listmodel.ListModelCombo):
    def __init__(self, **kwargs):
        self.name = kwargs.get('name', '')
        self.topwidget = Frame(label=self.name)
        #kwargs.setdefault('list_types', [str])
        #kwargs.setdefault('widget', gtk.ComboBox())
        super(Combo, self).__init__(**kwargs)
        self.topwidget.pack_start(self.widget)
            
class Button(gtk.Button):
    pass
    
class ToggleBtn(Toggle):
    def __init__(self, **kwargs):
        super(ToggleBtn, self).__init__(**kwargs)
        #self.topwidget = VBox()
        #self.topwidget.pack_start(self.widget)

class Slider(Fader):
    def __init__(self, **kwargs):
        super(Slider, self).__init__(**kwargs)
        self.topwidget = Frame(label=self.attribute.name)
        self.topwidget.pack_start(self.widget, expand=True)
        self.widget.set_digits(0)
        
class VSlider(Slider):
    def __init__(self, **kwargs):
        kwargs.setdefault('fader_type', 'VSlider')
        super(VSlider, self).__init__(**kwargs)
        self.widget_packing.update({'xoptions':gtk.FILL, 
                                    'yoptions':gtk.EXPAND | gtk.FILL})
        self.widget.set_property('inverted', True)
        #self.widget.set_property('width-request', 40)
        #self.widget.set_property('height-request', 128)
        
class HSlider(Slider):
    def __init__(self, **kwargs):
        kwargs.setdefault('fader_type', 'HSlider')
        super(HSlider, self).__init__(**kwargs)
        self.widget_packing.update({'xoptions':gtk.EXPAND | gtk.FILL, 
                                    'yoptions':gtk.FILL})
        #self.widget.set_property('width-request', 128)
        #self.widget.set_property('height-request', 40)




def get_widget_classes():
    return {'ToggleBtn':ToggleBtn, 'Radio':RadioBtn, 'VSlider':VSlider, 
            'HSlider':HSlider, 'Dial':HSlider, 'MenuBar':MenuBar}
def get_container_classes():
    return {'VBox':VBox, 'HBox':HBox, 'Table':Table, 'Frame':Frame, 
            'Expander':Expander, 'ScrolledWindow':ScrolledWindow, 'Notebook':Notebook}

